import os

from conan.tools.files import copy
from conan import ConanFile

from conan.tools.cmake import CMake, CMakeToolchain
from conan.tools.env import Environment


class ConanCppTemplate(ConanFile):
    name = 'conanCppTemplate'
    version = '0.0.1'
    license = 'MIT'
    author = 'yuzz'
    url = 'https://github.com/yzz-ihep/conanCppTemplate.git'
    description = 'conan template cpp project'
    topics = ('cpp', 'conan', 'template')
    settings = 'os', 'compiler', 'build_type', 'arch'
    options = {
        'shared': [True, False],
        'fPIC': [True, False],
    }
    default_options = {'shared': True, 'fPIC': True}

    # Sources are located in the same place as this recipe,
    # copy them to the recipe
    exports_sources = 'CMakeLists.txt', 'src/*', 'include/*'

    # 自己增加的环境变量, 将第三方依赖放在external_root
    # 在运行可执行文件时需要source setup.sh
    external_root = os.getenv('HOME') + '/conanenvs/base'
    CPLUS_INCLUDE_PATH = external_root + '/include'
    C_INCLUDE_PATH = external_root + '/include'
    LD_LIBRARY_PATH = external_root + '/lib'
    LIBRARY_PATH = external_root + '/lib'

    def requirements(self):
        self.requires('spdlog/1.11.0')
        self.requires('fmt/10.0.0')

    def build_requirements(self):
        self.tool_requires('cmake/3.22.6')

    def generate(self):
        tc = CMakeToolchain(self)
        # 不产生CMakeUserPresets.json
        tc.user_presets_path = False
        tc.generate()
        # 将第三方库拷贝到指定位置方便程序打包
        for dep in self.dependencies.values():
            print(
                dep.cpp_info.bindirs,
                dep.cpp_info.includedirs,
                dep.cpp_info.libdirs,
            )
            for dir in dep.cpp_info.bindirs:
                copy(self, '*', dir, self.external_root + '/bin')
            for dir in dep.cpp_info.includedirs:
                copy(self, '*', dir, self.CPLUS_INCLUDE_PATH)
            for dir in dep.cpp_info.libdirs:
                copy(self, '*', dir, self.LIBRARY_PATH)

        # 设置程序环境变量
        env = Environment()
        env.append_path('CPLUS_INCLUDE_PATH', self.CPLUS_INCLUDE_PATH)
        env.append_path('C_INCLUDE_PATH', self.C_INCLUDE_PATH)
        env.append_path('LD_LIBRARY_PATH', self.LD_LIBRARY_PATH)
        env.append_path('LIBRARY_PATH', self.LIBRARY_PATH)
        env.append_path('PATH', self.external_root + '/bin')
        envvars = env.vars(self)
        # 编译前需要执行source build/generators/setup.sh
        envvars.save_script('setup.sh')

    def layout(self):
        # define project folder structure
        self.folders.source = '.'
        self.folders.build = os.path.join(
            'build', str(self.settings.build_type)
        )
        # 设置generators产生位置
        self.folders.generators = os.path.join('build', 'generators')

        # cpp.package information is for consumers to find the
        # package contents in the Conan cache
        self.cpp.package.libs = ['say']
        self.cpp.package.includedirs = ['include']
        # includedirs is already set to 'include' by
        # default, but declared for completion

        self.cpp.package.libdirs = ['lib']
        # libdirs is already set to 'lib' by
        # default, but declared for completion

        # cpp.source and cpp.build information is specifically
        # designed for editable packages:
        # this information is relative to the source folder that is '.'
        self.cpp.source.includedirs = ['include']   # maps to ./include

        # this information is relative to the build folder that is
        # './build/<build_type>', so it will
        # map to ./build/<build_type> for libdirs
        self.cpp.build.libdirs = ['.']

    def config_options(self):
        self.options['spdlog'].shared = True
        self.options['fmt'].shared = True
        if self.settings.os == 'Windows':
            del self.options.fPIC

    def source(self):
        """Method used to retrieve the source code from
        any other external origin like github using"""
        pass

    def build(self):
        """This method is used to build the source code
        of the recipe using the desired commands. You can use your command
        line tools to invoke your build system or any of the build helpers
        provided with Conan."""

        cmake = CMake(self)
        cmake.configure()
        cmake.build()
        cmake.test()

    def package(self):
        cmake = CMake(self)
        cmake.install()

    def package_info(self):
        self.cpp_info.libs = ['hello']  # The libs to link against
